package com.bicon.botu.finance.payment.weixin.api;

import com.alibaba.fastjson.JSON;
import com.bicon.botu.finance.payment.weixin.utils.CodeUtil;
import com.bicon.botu.finance.payment.common.PaymentConstants;
import com.bicon.botu.core.base.common.entity.BaseResult;
import com.bicon.botu.finance.payment.repository.AppPaymentInfoRepository;
import com.bicon.botu.finance.payment.service.PayInfoService;
import com.bicon.botu.finance.payment.service.TransferService;
import com.bicon.botu.finance.payment.vo.WeChatPayParams;
import com.bicon.botu.finance.payment.weixin.utils.PayUtils;
import lombok.extern.log4j.Log4j;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * 微信支付，回调，提现
 *
 * @Author: 宋旭
 * @Date: Created in 11:07 2017/7/26/026
 */
@Service
@Log4j
public class WeChatPayService {

    @Autowired
    private AppPaymentInfoRepository appPaymentInfoRepository;

    @Autowired
    private PayInfoService payInfoService;

    @Autowired
    private TransferService transferService;

    /**
     * 向微信支付系统下单
     **/
    public String payToWeChat(String code, String appId, String mchId, String appKey, String cerPath, String orderNumber, String productTitle, float total) {
        String nonce_str = CodeUtil.Code(25);
        String params = WxPayApiConfig.createBookingParams(code, appId, mchId, productTitle, orderNumber, total,
                 PaymentConstants.WEBCHAT_PAY_NOTIFY, nonce_str, appKey);
        log.info("【微信支付预下单请求参数】 " + params);
        String result = WxPayApi.pushOrder(params);
        log.info("【微信支付预下单结果】 " + result);
        Map<String, String> resMp = PayUtils.decodeXml(result);
        if (resMp == null) {
            return null;
        }
        if (resMp.get("result_code").equals("SUCCESS")) {
            String timeStamp = (System.currentTimeMillis() / 1000)+"";
            String prepayid = resMp.get("prepay_id");
            String nonceStr = resMp.get("nonce_str");

            //注意参数放入顺序按a-z进行排序签名
            List<NameValuePair> packageParams = new ArrayList<NameValuePair>();
            packageParams.add(new BasicNameValuePair("appid", appId));
            packageParams.add(new BasicNameValuePair("noncestr", nonceStr));
            packageParams.add(new BasicNameValuePair("package", "Sign=WXPay"));
            packageParams.add(new BasicNameValuePair("partnerid", mchId));
            packageParams.add(new BasicNameValuePair("prepayid", prepayid));
            packageParams.add(new BasicNameValuePair("timestamp", timeStamp));
            //发起支付的paySign签名
            String paySign = PayUtils.genPackageSign(packageParams, appKey);

            WeChatPayParams payParams = new WeChatPayParams();
            payParams.setOrderNumber(orderNumber);
            payParams.setAppid(appId);
            payParams.setPrepayid(prepayid);
            payParams.setPartnerid(mchId);
            payParams.setNoncestr(nonceStr);
            payParams.setTimestamp(timeStamp);
            payParams.setSign(paySign);
            String pay = JSON.toJSON(payParams).toString();
            log.info("【微信支付预下单返回参数】 " + pay);
            return pay;
        }
        return null;
    }

    /**
     * 校验微信支付数据
     *
     * @param code
     * @param orderNumber
     * @return
     */
    public BaseResult checkwechatPayResult(String code, String appId, String appKey, String cerPath, String orderNumber) {
        try {
            String nonce_str = CodeUtil.Code(25);
            String params = WxPayApiConfig.createQueryOrderParams(code, appId, orderNumber, nonce_str, appKey);
            String result = WxPayApi.orderQuery(params, cerPath, appId);
            Map<String, String> resMp = PayUtils.decodeXml(result);
            if (resMp == null) {
                return new BaseResult(PaymentConstants.RESPONSE_CODE_500, PaymentConstants.RESPONSE_MESSAGE_500,  "微信返回出错");
            }
            for (Map.Entry<String, String> entry : resMp.entrySet()) {
                System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
            }
            if (resMp.get("result_code").equals("SUCCESS") && resMp.get("result_code").equals("SUCCESS")) {
                if (resMp.get("trade_state").equals("SUCCESS")) {
                    //支付成功
                    return new BaseResult(PaymentConstants.RESPONSE_CODE_200, PaymentConstants.RESPONSE_MESSAGE_200, "");
                } else {
                    return new BaseResult(PaymentConstants.RESPONSE_CODE_400, PaymentConstants.RESPONSE_MESSAGE_400, "");
                }
            }
            return new BaseResult(PaymentConstants.RESPONSE_CODE_400, PaymentConstants.RESPONSE_MESSAGE_400, "");
        } catch (Exception e) {
            log.info("error", e);
            return new BaseResult(PaymentConstants.RESPONSE_CODE_500, PaymentConstants.RESPONSE_MESSAGE_500, "");
        }
    }


    /**
     * 微信提现
     *
     * @param transferId 提现id
     * @param amount     金额
     * @param payeeName  提现人名称
     * @param remark     备注
     * @return
     */
    public boolean transferToWeChat(String appId, String appKey, String cerPath, String mchId, String transferId,
                                       String payeeAccount, String amount, String payeeName, String remark) {

        String nonce_str = CodeUtil.Code(25);
        String params = WxPayApiConfig.createWeChatTransferParams(appId, mchId,
                "",
                nonce_str, transferId,
                payeeAccount,
                payeeName,
                amount,
                remark,
                appKey);
        String result = WxPayApi.transfers(params, cerPath, appId);
        Map<String, String> resMp = PayUtils.decodeXml(result);
        if (null == resMp){
            return false;
        }
        if (resMp.get("return_code").equals("FAIL")) {
            return false;
        }
        if (resMp.get("result_code").equals("SUCCESS")) {
            return true;
        } else {
            if (resMp.get("err_code").equals("SYSTEMERROR")) {
                //如果返回系统异常需要发送查询请求再次确认
                return getTransferinfoToWeChat(appId, appKey, cerPath, mchId, transferId);
            } else {
                return false;
            }
        }
    }

    /**
     * 微信提现查询
     * @param appId
     * @param appKey
     * @param cerPath
     * @param mchId
     * @param transferId
     * @return
     */
    public boolean getTransferinfoToWeChat(String appId, String appKey, String cerPath, String mchId, String transferId) {
        String nonce_str = CodeUtil.Code(25);
        String params = WxPayApiConfig.createWeChatTransferinfoParams(appId, mchId, nonce_str, transferId, appKey);
        String result = WxPayApi.getTransferInfo(params, cerPath, mchId);
        Map<String, String> resMp = PayUtils.decodeXml(result);
        if (resMp == null) {
            return false;
        }
        for (Map.Entry<String, String> entry : resMp.entrySet()) {
            System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
        }
        if (resMp.get("result_code").equals("SUCCESS")) {
            return true;
        }
        return false;
    }

    /**
     * @param appid                  公众账号ID
     * @param mch_id                 商户号
     * @param transaction_id         微信订单号
     * @param out_trade_no           商户订单号
     * @param out_refund_no          商户退款单号
     * @param total_fee              订单金额
     * @param refund_fee             退款金额
     * @param refund_desc            退款原因
     * @param notify_url             退款结果通知url
     */
    public String refund(String appid, String mch_id, String transaction_id, String out_trade_no, String out_refund_no,
                       BigDecimal total_fee, BigDecimal refund_fee,String refund_desc, String notify_url,String appKey,
                                       String certPath,String certPassword) {

        Long totalAmount = total_fee.multiply(new BigDecimal("100")).longValue();
        Long refundAmount = refund_fee.multiply(new BigDecimal("100")).longValue();
        String params = WxPayApiConfig.createRefundParam(appid,mch_id,transaction_id,out_trade_no,out_refund_no,totalAmount,refundAmount,refund_desc,notify_url,appKey);
        String  result = WxPayApi.orderRefund(params, certPath, certPassword);
        return result;
    }
}
